package com.peng.contentproviderdemo;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by Mr.Q on 2017/12/21.
 * 描述:
 * 1、一下6个方法中，除了onCreate由系统回调并运行在主线程，其他方法由外界回调，并运行在Binder线程池中
 * 2、ContentProvider 主要以表格的形式来组织数据，除了表，还支持文件，比如图片，视频。
 * 3、因文件数据和表格数据结构不同，处理这类数据时可以在ContentProvider返回文件的句柄，从而让外界来访问ContentProvider中的文件信息
 * 4、ContentProvider 对底层数据的存储方式没有任何要求，可以是SQLite数据库，可以是文件，也可以是内存中的一个对象。
 */

public class BookContentProvider extends ContentProvider {

    private static final String TAG = "BookContentProvider";
    private Context mContext;
    //SQLiteDatabase 内部对数据库的操作是有做同步处理的。如果有多个SQLiteDatabase对象同时访问，就无法保证线程同步
    private SQLiteDatabase mDb;

    public static final String AUTHORITY = "com.peng.contentproviderdemo.BookContentProvider";

    // 该ContentProvider对外界提供了book、user表可访问
    // 为了知道外界要访问那个表，需要单独定义Uri和UriCode
    public static final Uri BOOK_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "book");
    public static final Uri USER_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "user");

    public static final int BOOK_URI_CODE = 0;
    public static final int USER_URI_CODE = 1;

    //通过UriMatcher和addURI方法将Uri和UriCode关联到一起
    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        sUriMatcher.addURI(AUTHORITY, "book", BOOK_URI_CODE);
        sUriMatcher.addURI(AUTHORITY, "user", USER_URI_CODE);
    }

    /**
     * 通过Uri匹配的方式获取表名
     *
     * @param uri
     * @return
     */
    private String getTableName(Uri uri) {
        String tableName = null;
        switch (sUriMatcher.match(uri)) {
            case BOOK_URI_CODE:
                tableName = DBOpenHelper.BOOK_TABLE_NAME;
                break;
            case USER_URI_CODE:
                tableName = DBOpenHelper.USER_TABLE_NAME;
                break;
            default:
                break;
        }
        return tableName;
    }

    @Override
    public boolean onCreate() {
        Log.d(TAG, "query: current thread" + Thread.currentThread().getName());
        mContext = getContext();
        initProviderData();
        return true;
    }

    private void initProviderData() {
        mDb = new DBOpenHelper(mContext).getWritableDatabase();
        mDb.execSQL("delete from " + DBOpenHelper.BOOK_TABLE_NAME);
        mDb.execSQL("delete from " + DBOpenHelper.USER_TABLE_NAME);
        mDb.execSQL("insert into book values(3,'Android');");
        mDb.execSQL("insert into book values(4,'IOS');");
        mDb.execSQL("insert into book values(5,'html');");
        mDb.execSQL("insert into book values(2,'java');");
        mDb.execSQL("insert into book values(1,'c++');");

    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        Log.d(TAG, "query: current thread" + Thread.currentThread().getName());
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }

        return mDb.query(tableName, projection, selection, selectionArgs, null, null, sortOrder, null);
    }

    /**
     * 该方法返回 URI 请求所对应的 MIME 类型
     *
     * @param uri
     * @return
     */
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        Log.d(TAG, "getType: ");

        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        Log.d(TAG, "insert: current thread" + Thread.currentThread().getName());
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        mDb.insert(tableName, null, contentValues);
        mContext.getContentResolver().notifyChange(uri, null);
        return uri;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        Log.d(TAG, "delete: current thread" + Thread.currentThread().getName());
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        int count = mDb.delete(tableName, selection, selectionArgs);
        if (count > 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return count;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String selection, @Nullable String[] selectionArgs) {
        Log.d(TAG, "update: current thread" + Thread.currentThread().getName());
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        int row = mDb.update(tableName, contentValues, selection, selectionArgs);
        if(row > 0){
            getContext().getContentResolver().notifyChange(uri,null);
        }
        return row;
    }
}
